#ifndef IOCTLCHANNEL_H
#define IOCTLCHANNEL_H

#include <atomic>
#include <memory>
#include <mutex>
#include <windows.h>

#define MSG_NAME_LENGTH 512

#define MSG_TYPE_EXE_ASK 0x01
#define MSG_TYPE_INSTALL_END 0x02
#define MSG_TYPE_DEBUG_ALL 0x04
#define MSG_TYPE_EXE_ALLOW 0x10
#define MSG_TYPE_EXE_DENY 0x20

#define MSG_STATE_IDLE 90
#define MSG_STATE_BUSY 91
#define MSG_STATE_DEVICE_OK 100

#pragma pack(push, 1)
struct IO_MSG {
    SHORT Id;
    SHORT Message;
    HANDLE CurrentPid;
    HANDLE ParentPid;
    WCHAR FileName[MSG_NAME_LENGTH];
    USHORT NameMaxLength;
};
#pragma pack(pop)

struct MSG_RECV {};

struct MSG_REPLY {};

class IoctlChannel {
public:
    IoctlChannel() = default;

    ~IoctlChannel();

    bool Connect();

    void Disconnect();

    bool Reply(IO_MSG &msg);

    bool Recv(IO_MSG &msg);

    static std::shared_ptr<IoctlChannel> GetInstance();

private:
    HANDLE Connect(const std::wstring &deviceName);

    HANDLE devices[2];  // 2: read/write device
    std::mutex sendLock = {};
    std::atomic<bool> isConnected{false};
};

#endif  // IOCTLCHANNEL_H
